package net.es.oscars.authZ.http;

import java.util.ArrayList;
import java.util.List;


import oasis.names.tc.saml._2_0.assertion.AttributeType;

import org.apache.log4j.Logger;
import org.hibernate.Session;

import net.es.oscars.authZ.beans.Attribute;
import net.es.oscars.authZ.common.AuthZCore;
import net.es.oscars.authZ.common.AuthZException;
import net.es.oscars.authZ.common.AuthZManager;
import net.es.oscars.authZ.soap.gen.AuthZPortType;
import net.es.oscars.authZ.soap.gen.CheckAccessParams;
import net.es.oscars.authZ.soap.gen.CheckAccessReply;
import net.es.oscars.authZ.soap.gen.CheckMultiAccessParams;
import net.es.oscars.authZ.soap.gen.MultiAccessPerm;
import net.es.oscars.authZ.soap.gen.MultiAccessPerms;
import net.es.oscars.authZ.soap.gen.PermType;
import net.es.oscars.authZ.soap.gen.ReqPermType;
import net.es.oscars.common.soap.gen.AuthConditionType;
import net.es.oscars.common.soap.gen.AuthConditions;
import net.es.oscars.common.soap.gen.OSCARSFaultMessage;
import net.es.oscars.common.soap.gen.SubjectAttributes;
import net.es.oscars.logging.ModuleName;
import net.es.oscars.logging.OSCARSNetLogger;
import net.es.oscars.logging.OSCARSNetLoggerize;
import net.es.oscars.utils.soap.OSCARSFaultUtils;
import net.es.oscars.utils.sharedConstants.AuthZConstants;
import net.es.oscars.utils.svc.ServiceNames;

/**
 * This class was generated by Apache CXF 2.2.2
 * Tue Jun 30 15:40:51 PDT 2009
 * Generated source version: 2.2.2
 *
 */

@OSCARSNetLoggerize(moduleName=ModuleName.AUTHZ)
@javax.jws.WebService(
    serviceName = ServiceNames.SVC_AUTHZ,
    portName = "AuthZPort",
    targetNamespace = "http://oscars.es.net/OSCARS/authZ",
    endpointInterface = "net.es.oscars.authZ.soap.gen.AuthZPortType")
@javax.xml.ws.BindingType(value = "http://www.w3.org/2003/05/soap/bindings/HTTP/")

public class AuthZSoapHandler implements AuthZPortType {

    private static final Logger LOG = Logger.getLogger(AuthZSoapHandler.class);
    private AuthZCore core = AuthZCore.getInstance();
    AuthZManager mgr = core.getAuthZManager();
    private String loginId;
    private String institution;
    private OSCARSNetLogger netLogger = null;
    private String event = null;

    /**
     *  CheckAccess takes a set of SubjectAttributes, a resource name and a requested action
     *      and returns a Permission and set of Conditions
     *  
     *  @param CheckAccessReqMsg contains set of SubjectAttributes, a resource name and a requested action
     *  @return CheckAccessReply containing a String permission "DENIED","ALLUSERS","SELFONLY"
     *        and a list of AuthConditions which may include permittedDomains, permittedLogin, internalHopsAllowed
     *        or may be empty.
     */
    public CheckAccessReply checkAccess(CheckAccessParams checkAccessReqMsg)
            throws OSCARSFaultMessage {

        this.event = "checkAccess";
        this.netLogger = OSCARSNetLogger.getTlogger();
        String transId = checkAccessReqMsg.getTransactionId();
        netLogger.init(ModuleName.AUTHZ, transId);
        LOG.info(netLogger.start(event));
        CheckAccessReply reply = new CheckAccessReply();
        Session session = core.getSession();
        try {
            session.beginTransaction();
            SubjectAttributes samlAttrs =
                checkAccessReqMsg.getSubjectAttrs();
            List<Attribute> beanAttrs = this.attributesToBeans(samlAttrs);
            String resourceName = checkAccessReqMsg.getResourceName();
            String permissionName = checkAccessReqMsg.getPermissionName();
            LOG.debug(netLogger.getMsg(event,"checkAccess resource: " + resourceName + 
                                       " permission: " + permissionName));
            LOG.debug(netLogger.getMsg(event,"number of attributes is " + beanAttrs.size()));
            reply = mgr.checkAccess(beanAttrs, resourceName, permissionName);
        } catch (Exception ex) {
            OSCARSFaultUtils.handleError ( ex, false, session, LOG, event);
        }
        session.getTransaction().commit();
        LOG.info(netLogger.end(event));
        
        return reply;
    }
 
    /**
     *  CheckMultiAccess takes a set of SubjectAttributes, a set of resource names and requested actions
     *      for each resource.
     *      It returns a set of Permission and Conditions for each resource and requested action
     *      It is designed to be called by the WBUI when setting up the tabs for a user view
     *  
     *  @param CheckMultiAccessReqMsg contains set of SubjectAttributes,  and a set of resource name and 
     *     requested actions
     *  @return MultiAccessPerms contains for each Resource 
     *      a requested action, 
     *      a String permission "DENIED","ALLUSERS","SELFONLY"
     *      and a list of AuthConditions which may include permittedDomains, permittedLogin, internalHopsAllowed
     *        or may be empty.
     */
    public MultiAccessPerms
        checkMultiAccess(CheckMultiAccessParams checkMultiAccessReqMsg)
            throws OSCARSFaultMessage {

        this.event = "checkMultiAccess";
        this.netLogger = OSCARSNetLogger.getTlogger();
        String transId = checkMultiAccessReqMsg.getTransactionId();
        netLogger.init(ModuleName.AUTHN, transId);
        LOG.info(netLogger.start(event));
        MultiAccessPerms reply = new MultiAccessPerms();
        AuthZManager mgr = core.getAuthZManager();
        Session session = core.getSession();
        try {
            session.beginTransaction();
            SubjectAttributes samlAttrs =
                checkMultiAccessReqMsg.getSubjectAttrs();
            List<Attribute> beanAttrs = this.attributesToBeans(samlAttrs);
            List<ReqPermType> resourcePermissions =
                checkMultiAccessReqMsg.getReqPermissions();
            List<MultiAccessPerm> accessPerms = reply.getAccessPerm();
            // check access for each combination
            for (ReqPermType rp: resourcePermissions) {
                // reply types
                MultiAccessPerm accessPerm = new MultiAccessPerm();
                List<PermType> permTypes = accessPerm.getPermissionGranted();
                // request parameters
                String resourceName = rp.getResource();
                List<String> permissions = rp.getReqAction();
                // for each requested resource and permission, get the authValues
                for (String permissionName: permissions) {
                    CheckAccessReply rep = mgr.checkAccess(beanAttrs, resourceName, permissionName);
                    // reply type
                    PermType permType = new PermType();
                    permType.setPermission(permissionName);
                    permType.setAction(rep.getPermission());
                    permType.setConditions(rep.getConditions());
                    permTypes.add(permType);
                }
                accessPerm.setResource(resourceName);
                accessPerms.add(accessPerm);
            }
        } catch (Exception ex) {
            OSCARSFaultUtils.handleError ( ex, false, session, LOG, event);
        }
        session.getTransaction().commit();
        LOG.info(netLogger.end(event));
        return reply;
    }

    private List<Attribute> attributesToBeans(SubjectAttributes samlAttrs) {
        List<Attribute> beanAttrs = new ArrayList<Attribute>();
        for (AttributeType samlAttr: samlAttrs.getSubjectAttribute()) {
            String attrId = samlAttr.getName();
            LOG.debug(this.netLogger.getMsg(this.event,"attrName is " + attrId));
            List<Object> samlValues = samlAttr.getAttributeValue();
            for (Object samlValue: samlValues) {
                Attribute attr = new Attribute();
                attr.setAttrId(attrId);
                attr.setValue((String) samlValue);
                LOG.debug(this.netLogger.getMsg(this.event,"attrValue is " + (String)samlValue));
                beanAttrs.add(attr);
                if (attrId.equals("loginId")) {
                    this.loginId = attr.getValue();  // there should only be one value in a loginId attribute
                }
                if (attrId.equals("institution")) {
                    this.institution = attr.getValue(); // there should only be one value in an institution attribute
                }
            }
        }
        return beanAttrs;
    }
}
